#include <vector>
#include <algorithm>
#include <iostream>

struct Fragment {
    int length;  // 分片长度（包括头部）
    int offset;  // 偏移量（以8字节为单位）
};
std::vector<Fragment> fragmentPacket(int packetLength, const std::vector<int>& pathMTUs) {
    std::vector<Fragment> fragments;

    // 报文头固定20字节，数据部分长度
    int headerSize = 20;
    int dataLength = packetLength - headerSize;

    if (dataLength <= 0) {
        // 如果报文长度小于等于头部大小，直接返回整个报文
        fragments.push_back({ packetLength, 0 });
        return fragments;
    }

    // 找到路径上的最小MTU
    int minMTU = *std::min_element(pathMTUs.begin(), pathMTUs.end());

    // 每个分片的数据部分最大长度（MTU减去头部）
    int maxDataPerFragment = minMTU - headerSize;

    // 确保每个分片的数据长度是8的倍数（IP分片要求）
    maxDataPerFragment = (maxDataPerFragment / 8) * 8;

    if (maxDataPerFragment <= 0) {
        // 如果MTU太小，无法容纳头部，返回空结果或错误处理
        return fragments;
    }

    // 计算需要多少分片
    int numFragments = (dataLength + maxDataPerFragment - 1) / maxDataPerFragment;

    int currentOffset = 0;
    int remainingData = dataLength;

    for (int i = 0; i < numFragments; i++) {
        int fragmentDataLength;

        if (i == numFragments - 1) {
            // 最后一个分片，使用剩余的所有数据
            fragmentDataLength = remainingData;
        }
        else {
            // 中间分片，使用最大数据长度
            fragmentDataLength = maxDataPerFragment;
        }

        // 分片总长度 = 数据长度 + 头部长度
        int fragmentTotalLength = fragmentDataLength + headerSize;

        // 添加到结果列表
        fragments.push_back({ fragmentTotalLength, currentOffset });

        // 更新偏移量和剩余数据量
        currentOffset += fragmentDataLength / 8;  // 偏移量以8字节为单位
        remainingData -= fragmentDataLength;
    }

    return fragments;
}
int main() {
    // 示例：1500字节的报文，路径MTU为1500, 1000, 576
    std::vector<int> pathMTUs = { 1500, 1000, 576 };
    std::vector<Fragment> result = fragmentPacket(1500, pathMTUs);

    // 输出分片结果
    for (const auto& frag : result) {
        std::cout << "Length: " << frag.length << ", Offset: " << frag.offset << std::endl;
    }

    return 0;
}